home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
User's Choice Windows CD
/
User's Choice Windows CD (CMS Software)(1993).iso
/
misc1
/
iv26_w30.zip
/
SOURCES
/
BOX.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-02-07
|
11KB
|
470 lines
/*
* Copyright (c) 1987, 1988, 1989 Stanford University
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided
* that the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Stanford not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. Stanford makes no representations about
* the suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* STANFORD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
* IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* Basic composite object for interaction.
*/
#include <InterViews/box.h>
#include <InterViews/shape.h>
class BoxElement {
public:
Interactor* child;
boolean visible;
BoxElement* next;
};
class BoxDimension {
public:
int natural;
int stretch;
int shrink;
};
class BoxCanonical {
public:
BoxDimension major;
BoxDimension minor;
};
Box::Box () : (nil, nil) {
nelements = 0;
head = nil;
tail = nil;
}
Box::~Box () {
register BoxElement* e;
register BoxElement* next;
for (e = head; e != nil; e = next) {
next = e->next;
delete e->child;
delete e;
}
}
void Box::Align (Alignment a) {
align = a;
}
void Box::DoInsert (Interactor* i, boolean, Coord&, Coord&) {
register BoxElement* e;
++nelements;
e = new BoxElement;
e->child = i;
e->next = nil;
if (head == nil) {
head = e;
tail = e;
} else {
tail->next = e;
tail = e;
}
}
void Box::DoChange (Interactor*) {
Reconfig();
}
void Box::DoRemove (Interactor* i) {
register BoxElement* e, * prev;
--nelements;
prev = nil;
for (e = head; e != nil; e = e->next) {
if (e->child == i) {
if (prev == nil) {
head = e->next;
} else {
prev->next = e->next;
}
if (e == tail) {
tail = prev;
}
delete e;
break;
}
prev = e;
}
ComputeShape(shape);
}
void Box::Reconfig () {
ComputeShape(shape);
}
void Box::Resize () {
register BoxElement* e; /* box element */
Shape aggrshape; /* combined shape of components */
BoxCanonical total; /* components' shape along major axis */
int major, minor; /* actual dimensions of box */
register int have; /* how much box is willing to change */
register int need; /* how much box needs to change to fit */
boolean grow; /* true if stretching, false if shrinking */
BoxCanonical s; /* element shape along major axis */
register int pos; /* where to put next element on major axis */
register int len; /* size of element along major axis */
register int n; /* temporary variable */
ComputeShape(&aggrshape);
GetActual(major, minor);
GetCanonical(&aggrshape, total);
n = total.major.natural;
if (major > n) {
/* more space than desired ==> stretch elements */
grow = true;
have = total.major.stretch;
need = min(major - n, have);
} else {
/* less (or equal) space than desired ==> (maybe) shrink elements */
grow = false;
have = total.major.shrink;
need = min(n - major, have);
}
pos = 0;
for (e = head; e != nil; e = e->next) {
GetCanonical(e->child->GetShape(), s);
len = s.major.natural;
if (have > 0) {
if (grow) {
n = int(double(s.major.stretch)*double(need)/double(have));
len += n;
have -= s.major.stretch;
} else {
n = int(double(s.major.shrink)*double(need)/double(have));
len -= n;
have -= s.major.shrink;
}
need -= n;
}
n = s.minor.natural;
if (n == 0) {
n = minor;
} else if (n > minor) {
n = max(n - s.minor.shrink, minor);
} else if (n < minor) {
n = min(n + s.minor.stretch, minor);
}
if (n > 0 && len > 0) {
e->visible = true;
PlaceElement(e->child, pos, len, minor, n);
} else {
e->visible = false;
}
pos += len;
}
}
void Box::Draw () {
register BoxElement* e;
for (e = head; e != nil; e = e->next) {
if (e->visible) {
e->child->Draw();
}
}
}
void Box::GetComponents (Interactor** c, int nc, Interactor**& a, int& n) {
register BoxElement* e;
register Interactor** ap;
n = nelements;
a = (n <= nc) ? c : new Interactor*[n];
ap = a;
for (e = head; e != nil; e = e->next) {
*ap++ = e->child;
}
}
inline BoxElement* Box::Head () {
return head;
}
/*
* Default virtuals.
*/
void Box::ComputeShape (Shape*) {}
void Box::GetActual (int& major, int& minor) {}
void Box::GetCanonical (Shape*, BoxCanonical&) {}
void Box::PlaceElement (Interactor*, Coord, int, int, int) {}
void HBox::Init () {
SetClassName("HBox");
align = Bottom;
shape->Rigid(0, 0, vfil, vfil);
}
HBox::HBox () {
Init();
}
HBox::HBox (Interactor* i1) {
Init();
Insert(i1);
}
HBox::HBox (Interactor* i1, Interactor* i2) {
Init();
Insert(i1);
Insert(i2);
}
HBox::HBox (Interactor* i1, Interactor* i2, Interactor* i3) {
Init();
Insert(i1);
Insert(i2);
Insert(i3);
}
HBox::HBox (Interactor* i1, Interactor* i2, Interactor* i3, Interactor* i4) {
Init();
Insert(i1);
Insert(i2);
Insert(i3);
Insert(i4);
}
HBox::HBox (
Interactor* i1, Interactor* i2, Interactor* i3, Interactor* i4,
Interactor* i5
) {
Init();
Insert(i1);
Insert(i2);
Insert(i3);
Insert(i4);
Insert(i5);
}
HBox::HBox (
Interactor* i1, Interactor* i2, Interactor* i3, Interactor* i4,
Interactor* i5, Interactor* i6
) {
Init();
Insert(i1);
Insert(i2);
Insert(i3);
Insert(i4);
Insert(i5);
Insert(i6);
}
HBox::HBox (
Interactor* i1, Interactor* i2, Interactor* i3, Interactor* i4,
Interactor* i5, Interactor* i6, Interactor* i7
) {
Init();
Insert(i1);
Insert(i2);
Insert(i3);
Insert(i4);
Insert(i5);
Insert(i6);
Insert(i7);
}
void HBox::ComputeShape (register Shape* box) {
register BoxElement* e;
register Shape* s;
register int vmin, vmax;
box->width = 0;
box->height = 0;
box->Rigid(0, 0, vfil, vfil);
vmin = -vfil;
vmax = vfil;
for (e = Head(); e != nil; e = e->next) {
s = e->child->GetShape();
box->width += s->width;
box->height = max(box->height, s->height);
box->hstretch += s->hstretch;
box->hshrink += s->hshrink;
vmin = max(s->height - s->vshrink, vmin);
vmax = min(s->height + s->vstretch, vmax);
}
box->vstretch = max(0, vmax - box->height);
box->vshrink = max(0, box->height - vmin);
}
void HBox::GetActual (int& major, int& minor) {
major = xmax + 1;
minor = ymax + 1;
}
void HBox::GetCanonical (register Shape* s, register BoxCanonical& b) {
b.major.natural = s->width;
b.major.shrink = s->hshrink;
b.major.stretch = s->hstretch;
b.minor.natural = s->height;
b.minor.shrink = s->vshrink;
b.minor.stretch = s->vstretch;
}
void HBox::PlaceElement (Interactor* i, Coord x, int length, int size, int h) {
Coord x1, y1, x2, y2;
x1 = x;
if (align == Top) {
y1 = size - h;
} else if (align == Center) {
y1 = (size - h) / 2;
} else /* Bottom */ {
y1 = 0;
}
x2 = x1 + length - 1;
y2 = y1 + h - 1;
Place(i, x1, y1, x2, y2);
}
void VBox::Init () {
SetClassName("VBox");
align = Left;
shape->Rigid(hfil, hfil, 0, 0);
}
VBox::VBox () {
Init();
}
VBox::VBox (Interactor* i1) {
Init();
Insert(i1);
}
VBox::VBox (Interactor* i1, Interactor* i2) {
Init();
Insert(i1);
Insert(i2);
}
VBox::VBox (Interactor* i1, Interactor* i2, Interactor* i3) {
Init();
Insert(i1);
Insert(i2);
Insert(i3);
}
VBox::VBox (Interactor* i1, Interactor* i2, Interactor* i3, Interactor* i4) {
Init();
Insert(i1);
Insert(i2);
Insert(i3);
Insert(i4);
}
VBox::VBox (
Interactor* i1, Interactor* i2, Interactor* i3, Interactor* i4,
Interactor* i5
) {
Init();
Insert(i1);
Insert(i2);
Insert(i3);
Insert(i4);
Insert(i5);
}
VBox::VBox (
Interactor* i1, Interactor* i2, Interactor* i3, Interactor* i4,
Interactor* i5, Interactor* i6
) {
Init();
Insert(i1);
Insert(i2);
Insert(i3);
Insert(i4);
Insert(i5);
Insert(i6);
}
VBox::VBox (
Interactor* i1, Interactor* i2, Interactor* i3, Interactor* i4,
Interactor* i5, Interactor* i6, Interactor* i7
) {
Init();
Insert(i1);
Insert(i2);
Insert(i3);
Insert(i4);
Insert(i5);
Insert(i6);
Insert(i7);
}
void VBox::ComputeShape (register Shape* box) {
register BoxElement* e;
register Shape* s;
register int hmin, hmax;
box->width = 0;
box->height = 0;
box->Rigid(hfil, hfil, 0, 0);
hmin = -hfil;
hmax = hfil;
for (e = Head(); e != nil; e = e->next) {
s = e->child->GetShape();
box->width = max(box->width, s->width);
box->height += s->height;
box->vstretch += s->vstretch;
box->vshrink += s->vshrink;
hmin = max(s->width - s->hshrink, hmin);
hmax = min(s->width + s->hstretch, hmax);
}
box->hstretch = max(0, hmax - box->width);
box->hshrink = max(0, box->width - hmin);
}
void VBox::GetActual (int& major, int& minor) {
major = ymax + 1;
minor = xmax + 1;
}
void VBox::GetCanonical (register Shape* s, register BoxCanonical& b) {
b.major.natural = s->height;
b.major.shrink = s->vshrink;
b.major.stretch = s->vstretch;
b.minor.natural = s->width;
b.minor.shrink = s->hshrink;
b.minor.stretch = s->hstretch;
}
void VBox::PlaceElement (Interactor* i, Coord y, int length, int size, int w) {
Coord x1, y1, x2, y2;
if (align == Right) {
x1 = size - w;
} else if (align == Center) {
x1 = (size - w) / 2;
} else /* Left */ {
x1 = 0;
}
x2 = x1 + w - 1;
y2 = ymax - y;
y1 = y2 - length + 1;
Place(i, x1, y1, x2, y2);
}